package edu.cuit.zhuyimeng.gateway.filter;

import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import edu.cuit.zhuyimeng.framework.common.result.CommonResult;
import edu.cuit.zhuyimeng.framework.common.result.HttpStatusCodeConstants;
import edu.cuit.zhuyimeng.framework.common.security.UserContext;
import edu.cuit.zhuyimeng.gateway.property.DynamicGatewayProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
@EnableConfigurationProperties(DynamicGatewayProperties.class)
@RequiredArgsConstructor
public class GlobalAuthenticationFilter {

    private final DynamicGatewayProperties dynamicGatewayProperties;

    /**
     * 鉴权过滤器
     */
    @Bean
    @SuppressWarnings("unchecked")
    public SaReactorFilter getGlobalFilter() {

        return new SaReactorFilter()
                .addInclude("/**")    /* 拦截全部path */
                .addExclude("/favicon.ico")
                .setAuth(obj -> {

                    //获取token
                    ServerWebExchange context = SaReactorSyncHolder.getContext();
                    List<String> token = context.getRequest().getHeaders().get(StpUtil.getTokenName());
                    if (token != null && !StrUtil.isBlankIfStr(token.get(0))) {
                        UserContext.setToken(token.get(0));
                    }

                    //鉴定权限
                    for (Map<String, Object> entry : dynamicGatewayProperties.getPermissions()) {
                        String path = entry.get("path").toString();
                        Object permSection = entry.get("perms");
                        if (permSection != null) {
                            LinkedHashMap<String ,String> perms = (LinkedHashMap<String ,String>) permSection;
                            perms.forEach((key,value) ->  SaRouter.match(path).check(r -> StpUtil.checkPermission(value)));
                        }

                        //鉴定角色
                        Object roleSection = entry.get("roles");
                        if (roleSection != null) {
                            LinkedHashMap<String ,String> roles = (LinkedHashMap<String ,String>) roleSection;
                            roles.forEach((key, value) ->  SaRouter.match(path).check(r -> StpUtil.checkRole(value)));
                        }

                    }

                })
                .setError((e) -> {
                    //处理异常
                    ServerWebExchange context = SaReactorSyncHolder.getContext();
                    ServerHttpResponse response = context.getResponse();
                    response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
                    if (e instanceof ResponseStatusException exception) {
                        response.setStatusCode(exception.getStatusCode());
                    } else {
                        response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
                    }
                    context.mutate().response(response);
                    SaReactorSyncHolder.setContext(context);
                    return JSONUtil.toJsonStr( CommonResult.error(HttpStatusCodeConstants.FORBIDDEN,e.getMessage()));
                });
    }

}
